React Server Components

'use server' se utiliza con React Server Components.

'use server' marca funciones del lado del servidor que pueden llamarse desde el código del lado del cliente.


Referencia

'use server'

Añade 'use server' al principio del cuerpo de una función asíncrona para marcar la función como invocable desde el cliente. Llamamos a estas funciones Server Functions.

async function addToCart(data) {
'use server';
// ...
}

Cuando se llama a una Server Function desde el cliente, se realizará una petición de red al servidor que incluye una copia serializada de cualquier argumento pasado. Si la Server Function devuelve un valor, ese valor será serializado y devuelto al cliente.

En lugar de marcar funciones individualmente con 'use server', puedes añadir la directiva al principio de un archivo para marcar todas las funciones exportadas dentro de ese archivo como Server Functions, que pueden usarse en cualquier lugar, inclusive en código cliente.

Advertencias

  • 'use server' debe estar al principio de su función o módulo; por encima de cualquier otro código incluyendo importaciones (los comentarios por encima de las directivas están permitidos). Deben escribirse con comillas simples o dobles, no con comillas invertidas.
  • 'use server' solo puede usarse en archivos del lado del servidor. Las Server Functions resultantes pueden pasarse a Client Components a través de props. Consulta los tipos compatibles para serialización.
  • Para importar Server Functions desde código cliente, la directiva debe usarse a nivel de módulo.
  • Debido a que las llamadas de red subyacentes son siempre asíncronas, 'use server' solo puede usarse en funciones asíncronas.
  • Siempre trata los argumentos de las Server Functions como entradas no confiables y autoriza cualquier mutación. Consulta consideraciones de seguridad.
  • Las Server Functions deben llamarse en una Transición. Las Server Functions pasadas a <form action> o formAction se llamarán automáticamente en una transición.
  • Las Server Functions están diseñadas para mutaciones que actualizan el estado del servidor; no se recomiendan para la obtención de datos. En consecuencia, los frameworks que implementan Server Functions típicamente procesan una acción a la vez y no tienen una forma de almacenar en caché el valor de retorno.

Consideraciones de seguridad

Los argumentos de las Server Functions están completamente controlados por el cliente. Por seguridad, siempre trátalos como entradas no confiables y asegúrate de validar y escapar los argumentos según corresponda.

En cualquier Server Function, asegúrate de validar que el usuario conectado está autorizado para realizar esa acción.

En construcción

Para evitar el envío de datos sensibles desde una Server Function, hay APIs experimentales de taint para evitar que valores y objetos únicos se pasen al código cliente.

Consulta experimental_taintUniqueValue y experimental_taintObjectReference.

Argumentos y valores de retorno serializables

Dado que el código cliente llama a la Server Function a través de la red, cualquier argumento pasado necesitará ser serializable.

Aquí están los tipos compatibles para argumentos de Server Functions:

Notablemente, estos no son compatibles:

  • Elementos de React, o JSX
  • Funciones, incluyendo funciones de componente o cualquier otra función que no sea una Server Function
  • Clases
  • Objetos que son instancias de cualquier clase (aparte de las incorporadas mencionadas) u objetos con un prototipo nulo
  • Símbolos no registrados globalmente, ej. Symbol('my new symbol')
  • Eventos de controladores de eventos.

Los valores de retorno serializables compatibles son los mismos que las props serializables para una barrera de Client Component.

Uso

Server Functions en formularios

El caso de uso más común de las Server Functions será llamar a funciones que mutan datos. En el navegador, el elemento HTML form es el enfoque tradicional para que un usuario envíe una mutación. Con React Server Components, React introduce soporte de primera clase para Server Functions como Acciones en formularios.

Aquí hay un formulario que permite solicitar un nombre de usuario.

// App.js

async function requestUsername(formData) {
'use server';
const username = formData.get('username');
// ...
}

export default function App() {
return (
<form action={requestUsername}>
<input type="text" name="username" />
<button type="submit">Request</button>
</form>
);
}

En este ejemplo requestUsername es una Server Function pasada a un <form>. Cuando un usuario envía este formulario, hay una petición de red a la función del servidor requestUsername. Al llamar a una Server Function en un formulario, React proporcionará el FormData del formulario como el primer argumento de la Server Function.

Al pasar una Server Function a la action del formulario, React puede mejorar progresivamente el formulario. Esto significa que los formularios pueden enviarse antes de que se cargue el bundle de JavaScript.

Manejo de valores de retorno en formularios

En la solicitud del formulario podría estar la posibilidad de que un nombre de usuario no esté disponible. requestUsername debería decirnos si falla o no.

Para actualizar la UI en base al resultado de una Server Function mientras se soporta mejora progresiva, usa useActionState.

// requestUsername.js
'use server';

export default async function requestUsername(formData) {
const username = formData.get('username');
if (canRequest(username)) {
// ...
return 'successful';
}
return 'failed';
}
// UsernameForm.js
'use client';

import { useActionState } from 'react';
import requestUsername from './requestUsername';

function UsernameForm() {
const [state, action] = useActionState(requestUsername, null, 'n/a');

return (
<>
<form action={action}>
<input type="text" name="username" />
<button type="submit">Request</button>
</form>
<p>Last submission request returned: {state}</p>
</>
);
}

Ten en cuenta que como la mayoría de los Hooks, useActionState solo puede llamarse en código cliente.

Llamar a una Server Function fuera de <form>

Las Server Functions son endpoints del servidor expuestos y pueden llamarse desde cualquier lugar en el código cliente.

Cuando uses una Server Function fuera de un formulario, llama a la Server Function en una Transición, lo que te permite mostrar un indicador de carga, mostrar actualizaciones de estado optimistas, y manejar errores inesperados. Los formularios envolverán automáticamente las Server Functions en transiciones.

import incrementLike from './actions';
import { useState, useTransition } from 'react';

function LikeButton() {
const [isPending, startTransition] = useTransition();
const [likeCount, setLikeCount] = useState(0);

const onClick = () => {
startTransition(async () => {
const currentCount = await incrementLike();
setLikeCount(currentCount);
});
};

return (
<>
<p>Total Likes: {likeCount}</p>
<button onClick={onClick} disabled={isPending}>Like</button>;
</>
);
}
// actions.js
'use server';

let likeCount = 0;
export default async function incrementLike() {
likeCount++;
return likeCount;
}

Para leer un valor de retorno de una Server Function, necesitas usar await en la promesa que retorna.